#include "gate_drivers.h"
#include "main.h"
#include "printf.h"
// 7bit 地址
#define SlaveAddr 0x47
// 内部寄存器列表
#define POWMNG 0x01
#define LOGIC  0x02
#define READY  0x07
#define NFAULT 0x08
#define CLEAR  0x09
#define STBY   0x0A
#define LOCK   0x0B
#define RESET  0x0C
#define STATUS 0x80

// 读取寄存器
static uint8_t I2C_ReadRegister(uint8_t addr_reg){
    // 向地址为0x47的设备发送一个字节
    LL_I2C_HandleTransfer(
        I2C3,                     // I2C外设
        SlaveAddr << 1,           // 目标地址（左移1位）
        LL_I2C_ADDRSLAVE_7BIT,    // 7位地址模式
        1,                        // 传输字节数
        LL_I2C_MODE_AUTOEND,      // 自动结束模式
        LL_I2C_GENERATE_START_WRITE // 生成起始条件+写请求
    );
    while (!LL_I2C_IsActiveFlag_TXIS(I2C3)); // 等待发送寄存器就绪
    LL_I2C_TransmitData8(I2C3, addr_reg); // 发送数据
    while (!LL_I2C_IsActiveFlag_STOP(I2C3));  // 等待停止条件完成
    LL_I2C_ClearFlag_STOP(I2C3);              // 清除停止标志

    // 从地址为0x47的设备接收一个字节
    LL_I2C_HandleTransfer(
        I2C3,                     // I2C外设
        SlaveAddr << 1,           // 目标地址（左移1位）
        LL_I2C_ADDRSLAVE_7BIT,    // 7位地址模式
        1,                        // 接收字节数
        LL_I2C_MODE_AUTOEND,      // 自动结束模式
        LL_I2C_GENERATE_START_READ // 生成起始条件+读请求
    );
    while (!LL_I2C_IsActiveFlag_RXNE(I2C3));  // 等待接收完成
    uint8_t data_received = LL_I2C_ReceiveData8(I2C3); // 读取数据
    while (!LL_I2C_IsActiveFlag_STOP(I2C3));  // 等待停止条件完成
    LL_I2C_ClearFlag_STOP(I2C3);              // 清除停止标志

    return data_received;
}

// 写入寄存器
static void I2C_WriteRegister(uint8_t addr_reg, uint8_t value){
    // 配置传输：发送两个字节（寄存器地址 + 数据值）
    LL_I2C_HandleTransfer(
        I2C3,                     // I2C外设
        SlaveAddr << 1,           // 目标地址（左移1位）
        LL_I2C_ADDRSLAVE_7BIT,    // 7位地址模式
        2,                        // 传输字节数（地址+数据）
        LL_I2C_MODE_AUTOEND,      // 自动结束模式
        LL_I2C_GENERATE_START_WRITE // 生成起始条件+写请求
    );

    // 等待发送寄存器就绪并发送寄存器地址
    while (!LL_I2C_IsActiveFlag_TXIS(I2C3));
    LL_I2C_TransmitData8(I2C3, addr_reg);

    // 等待发送寄存器就绪并发送数据值
    while (!LL_I2C_IsActiveFlag_TXIS(I2C3));
    LL_I2C_TransmitData8(I2C3, value);

    // 等待传输完成（停止条件）
    while (!LL_I2C_IsActiveFlag_STOP(I2C3));
    LL_I2C_ClearFlag_STOP(I2C3);
}

// 读取全部寄存器的状态
void dump_gate_driver_regs(void)
{
    const uint8_t addr_list[] = {0x01, 0x02, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x80};
    for(int i=0; i<(int)sizeof(addr_list); i++){
        uint8_t addr = addr_list[i];
        printf_("addr = 0x%02X, val = 0x%02X\n", addr, I2C_ReadRegister(addr));
    }
}

void clear_gate_driver_fault(void){
    I2C_WriteRegister(CLEAR, 0xFF);
}

void config_gate_driver(void)
{
    // 解锁设备
    I2C_WriteRegister(LOCK, 0xA5);
    if(I2C_ReadRegister(LOCK) != 0xA5){
        printf_("failed to unlock\n");
    }
    // 配置驱动逻辑：01111011
    // 0111: rsv
    // 10: Deglitch set to 3 µs（默认6us，调低一些防止出现问题烧MOS）
    // 1: Minimum deadtime insertion Enabled
    // 1: Interlocking function Enabled
    I2C_WriteRegister(LOGIC, 0x7B);
    // 配置电压（8V）STSPIN32G4内部的LDO，工作在8V转3.3V模式，发热量更小，约70%
    I2C_WriteRegister(POWMNG, 0x00);
    // 锁定设备
    I2C_WriteRegister(LOCK, 0x00);
}

int check_gate_driver_error(void)
{
    int error =  I2C_ReadRegister(STATUS);
    if(!(error & (1 << 7))){
        printf_("protected registers not locked\n");
    }
    if(error & (1 << 2)){
        printf_("VDS Protection triggered\n");
    }
    if(error & (1 << 1)){
        printf_("Device in thermal shutdown\n");
    }
    if(error & (1 << 0)){
        printf_("Device in VCC UVLO\n");
    }
    return error;
}

